package com.sfy.login.service.impl;

import com.alibaba.fastjson.JSON;
import com.sfy.login.common.CommonString;
import com.sfy.login.common.RedisKey;
import com.sfy.login.dao.UserDao;
import com.sfy.login.dao.UserLogDao;
import com.sfy.login.dto.request.LoginRequest;
import com.sfy.login.entity.User;
import com.sfy.login.entity.UserLog;
import com.sfy.login.service.LoginService;
import com.sfy.login.third.JedisUtil;
import com.sfy.login.third.JwtUtil;
import com.sfy.login.vo.R;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Date;


/**
 * 登录模板
 */
public abstract class AbstarctLoginService implements LoginService {
    @Autowired
    private UserDao userDao;
    @Autowired
    private UserLogDao userLogDao;

    /**
     * 留给子类扩展
     * 实现该类返回自己对应的登录属性
     * @return
     */
    public abstract String getLoginType();

    /**
     * 获取对应的code
     */
    public abstract String getCode(User user);

    /**
     * 删除指定key
     * 作为登陆后的清理行为
     */
    public abstract void removeLoginCache(User user);

    /**
     * 判断是否是对应策略
     */
    @Override
    public Boolean supports(String loginType) {
        return getLoginType().equals(loginType);
    }

    @Override
    public R login(LoginRequest request, String ip) {
        //账号合法性校验
        User user = checkUserStatus(request);
        //真正的登陆操作
        if (request.getCode().equals(getCode(user))) {
            //登陆成功操作
            loginSuccess(user,ip);
            //清理短信验证，邮箱验证码等
            removeLoginCache(user);
            return R.ok();
        }else {
            //登录失败操作
            loginFail(user,ip);
            return R.fail();
        }
    }

    /**
     * 登录失败的处理
     *
     * @param user
     */
    private void loginFail(User user,String ip) {
        //todo 待补充其他限制，如连续登录失败后，限制登录
        System.out.println("登录失败");
    }

    /**
     * 登录成功处理
     */
    private void loginSuccess(User user,String ip) {
        if (!JedisUtil.checkKey(RedisKey.USER_TOKEN_ID + user.getId())) {
            //生成令牌
            String token = JwtUtil.createJwt(user.getId().toString());
            //存储令牌
            JedisUtil.addStr(RedisKey.USER_TOKEN_ID + user.getId(), token, RedisKey.USER_TOKEN_TIME);
            JedisUtil.addStr(RedisKey.USER_TOKEN + token, JSON.toJSONString(user), RedisKey.USER_TOKEN_TIME);
            userLogDao.insertUserLog(new UserLog(user.getId(), CommonString.USER_LOG_4,ip,new Date()));
        }else {
            userLogDao.insert(new UserLog(user.getId(),CommonString.USER_LOG_8,ip,new Date()));
        }
    }

    protected User checkUserStatus(LoginRequest request) {
        User query = new User();
        BeanUtils.copyProperties(request,query);
        User realUser = userDao.selectByUser(query);
        if (realUser != null) {
            if (realUser.getFlag().equals(CommonString.USER_LOG_9)) {
                throw new RuntimeException("账号异常，请联系工作人员处理");
            }
            return realUser;
        }
        throw new RuntimeException("账号不存在");
    }

}
